package com.xxjh.brs.sftp.service.impl;

import cn.hutool.extra.ssh.Sftp;
import com.xxjh.brs.sftp.vo.FileVo;
import com.xxjh.brs.sftp.vo.FloderVo;
import com.xxjh.brs.sftp.common.predicate.SftpPredicate;
import com.xxjh.brs.sftp.common.utils.SftpConstantsUtil;
import com.xxjh.brs.sftp.factory.SftpProperties;
import com.xxjh.brs.sftp.service.AbstractSftpService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.ObjectPool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author CHENCHEN
 * @title a
 * @company 新兴际华科技（天津）有限公司
 * @create 2024-07-04 16:27
 */
@Slf4j
@Service
@Scope("prototype")
public class PushSftpService extends AbstractSftpService {

    @Autowired
    @Qualifier("sftpClientPoolPush")
    private ObjectPool<Sftp> sftpClientPoolPush;

    @Value("${sftp.pushServer.pusherDir}")
    protected String pusherDir;

    @Value("${sftp.pushServer.root}")
    protected String rootPath;

    @Autowired
    private SftpProperties sftpProperties;

    @Override
    protected ObjectPool<Sftp> getSftpClientPool() {
        return sftpClientPoolPush;
    }

    /**
     * 本地文件上传到FTP服务器。
     * 支持多级目录文件
     *
     * @param drictoryPath FTP目标服务器根路径下具体某文件夹路径。
     * @param specifiedLayer 代表指定目录。
     * @param appoint 指定目录下没有目录只有文件（true没有目录，false还有目录）。
     *
     */
    public void localDirectoryUploadToFtp(String drictoryPath, String specifiedLayer, boolean appoint){
        Sftp sftpClient = null;
        try {
            sftpClient = getSFTPClient(rootPath);
            if(appoint){
                uploadLocalDirectoryFileFtp(pusherDir, drictoryPath + specifiedLayer);
            }else{
                uploadLocalFtp(pusherDir, drictoryPath + specifiedLayer);
            }
        }finally {
            try {
                sftpClientPoolPush.returnObject(sftpClient);
            } catch (Exception e) {
                log.info("回收连接异常....");
            }
        }
    }

    /**
     * 查找FTP服务器指定文件夹下是否存在指定文件并返回路径。
     *
     * @param drictoryPath FTP目标服务器根路径下具体某文件夹路径。
     * @param specifiedLayer 有值代表指定目录，无值检索全部。
     * @param sftpPredicate    断言，匹配满足需求的文件及目录。
     * @return FTP服务器现所有指定规则文件存放路径。
     */
    public List<FileVo> findFtpCustomizedDirectory(String drictoryPath, String specifiedLayer, SftpPredicate sftpPredicate){
        Sftp sftpClient = null;
        try {
            sftpClient = getSFTPClient(rootPath);
            return searcherFtpCustomizedDirectory(pusherDir + drictoryPath, specifiedLayer, sftpPredicate);
        }finally {
            try {
                sftpClientPoolPush.returnObject(sftpClient);
            } catch (Exception e) {
                log.info("回收连接异常....");
            }
        }
    }

    /**
     * FTP获取资源服务器指定文件夹最后更新时间
     *
     * @param drictoryPath 指定路径。
     * @param specifiedLayer 文件夹名称。
     * @return 当前文件夹属性类。
     */
    public FloderVo findLastUpdateFloder(String drictoryPath, String specifiedLayer){
        Sftp sftpClient = null;
        try {
            sftpClient = getSFTPClient(rootPath);
            return lastUpdateFloderProperties(pusherDir + drictoryPath, specifiedLayer);
        }finally {
            try {
                sftpClientPoolPush.returnObject(sftpClient);
            } catch (Exception e) {
                log.info("回收连接异常....");
            }
        }
    }

    /**
     * 删除FTP服务器指定目录及其所有内容（包括子目录和文件）。
     *
     * @param typeLayer 根目录后的指定目录。
     * @param directoryPath 目录下要删除的目录。
     * @return 如果目录及其内容成功删除则返回true，否则返回false。
     */
    public boolean deleteFtpDirectory(String typeLayer, String directoryPath){
        Sftp sftp = SftpConstantsUtil.createClient(sftpProperties.getPushServer());
        try {
            setSeparateClient(sftp, rootPath);;
            return delDirAndFile(sftpParentPath + pusherDir + typeLayer + directoryPath);
        }finally {
            sftp.close();
        }
    }
}
